--  ------------------------------------------------------------------------
--  @File: part.ads
--
--  @Project: liberAda
--  @Author: Markus Knauss, Julian Trischler
--  @Created: 2009-11-17
--  @Version: 1.0
--
--  @Description:
--    A part of a document. Each part has attributes that forego its content
--    and attributes that follow its content. For instance, if part objects
--    are used for a html document and the following content is to be
--    modeled: <a href="file">File</a>. The foregoing attributes are
--    <a href="file">, the content is File, and the following attributes
--    are </a>.
--
--    Parts are hierarchically structured. A part can contain an unlimited
--    number of sub-parts.
--
--  @Usage:
--    Before a part is used it must be created using the (@see: Create)
--    function. When the part is needed no more it should be destroyed
--    using the (@see: Destroy) procedure. Between create and destroy of
--    a part any other routines can be used.
--
--  @Modifications:
--    +2009-11-17 MK: Initial release
--    +2011-04-14 JT: Added title, level and anchor handling
with Ada.Strings.Unbounded;
with Ada.Containers.Vectors;

package Part is

   package ASU renames Ada.Strings.Unbounded;

   --  ----------------------------------------------------------------------
   --  @Type: Part_Type
   --  @Purpose: Type for a part
   type Part_Type is private;

   --  ----------------------------------------------------------------------
   --  @Type: Parts_Type
   --  @Purpose: To handle many parts
   type Parts_Type is array (Natural range <>) of Part_Type;

   --  ----------------------------------------------------------------------
   --  @Type: Attributes_Type
   --  @Purpose: Type for the attributes that forego and follow the content
   --    of a part
   type Attributes_Type is array (Natural range <>) of ASU.Unbounded_String;

   --  ----------------------------------------------------------------------
   --  @Type: Level_Type
   --  @Purpose: Type for title levels. It will be parsed to <h1> .. <h6>.
   --    A value of 0 means no title level.
   type Level_Type is range 0 .. 6;

   --  ----------------------------------------------------------------------
   --  @Function: Create
   --  @Description:
   --    Creates a new part with empty title, level and anchor.
   function Create return Part_Type;

   --  ----------------------------------------------------------------------
   --  @Function: Create
   --  @Description:
   --    Creates a new part with given title, level and anchor.
   --  @Parameter:
   --    +Anchor: the anchor for hyerlinks
   --    +Title: the title for blocks
   --    +Level: the title level
   function Create
     (Anchor : in String;
      Title  : in String;
      Level  : in Level_Type) return Part.Part_Type;

   --  ----------------------------------------------------------------------
   --  @Function: Create_Part
   --  @Description: Creates a new simple part whose content is enclosed
   --    within the given tag.
   function Create_Part
     (Value : in String;
      Tag   : in String) return Part.Part_Type;

   --  ----------------------------------------------------------------------
   --  @Function: Exists
   --  @Description: Determines if this part was created.
   --  @Return: True if part was created otherwise false
   function Exists (Part : in Part_Type) return Boolean;

   --  ----------------------------------------------------------------------
   --  @Procedure: Destroy
   --  @Description: Destroys the given part by freeing all allocated
   --    resources.
   procedure Destroy (Part : in out Part_Type);

   --  ----------------------------------------------------------------------
   --  @Procedure: Add_Attribute_Before
   --  @Description:
   --    Adds the given attribute before the content.
   procedure Add_Attribute_Before
     (Part : in out Part_Type;
      Attr : in     String);

   --  ----------------------------------------------------------------------
   --  @Function: Has_Attributes_Before
   --  @Description:
   --    Determines if this part has attributes before its content.
   function Has_Attributes_Before (Part : in Part_Type) return Boolean;

   --  ----------------------------------------------------------------------
   --  @Function: Attributes_Before
   --  @Description:
   --    Returns all attributes that are before the part's content
   function Attributes_Before (Part : in Part_Type) return Attributes_Type;

   --  ----------------------------------------------------------------------
   --  @Procedure: Add_Attribute_After
   --  @Description:
   --    Adds an attribute after the part's content
   procedure Add_Attribute_After
     (Part : in out Part_Type;
      Attr : in     String);

   --  ----------------------------------------------------------------------
   --  @Function: Has_Attributes_After
   --  @Description:
   --    Determines if this part has attributes after its content
   function Has_Attributes_After (Part : in Part_Type) return Boolean;

   --  ----------------------------------------------------------------------
   --  @Function: Attributes_After
   --  @Description: Returns all attributes after this part's content
   function Attributes_After (Part : in Part_Type) return Attributes_Type;

   --  ----------------------------------------------------------------------
   --  @Procedure: Set_Value
   --  @Description: Sets the content for this part
   procedure Set_Value
     (Part  : in out Part_Type;
      Value : in     String);

   --  ----------------------------------------------------------------------
   --  @Function: Value
   --  @Description: Returns the content of this part
   function Value (Part : in Part_Type) return String;

   --  ----------------------------------------------------------------------
   --  @Procedure: Add_Part
   --  @Description:
   --    Adds a sub-part to this part.
   procedure Add_Part
     (Part     : in out Part_Type;
      Sub_Part : in     Part_Type);

   --  ----------------------------------------------------------------------
   --  @Function: Has_Parts
   --  @Description:
   --    Determines if this part has sub-parts
   function Has_Parts (Part : in Part_Type) return Boolean;

   --  ----------------------------------------------------------------------
   --  @Function: Parts
   --  @Description: Returns the sub-parts if this part
   function Parts (Part : in Part_Type) return Parts_Type;

   --  ----------------------------------------------------------------------
   --  @Function: Anchor
   --  @Description: Returns the part's anchor for hyperlinking.
   --  @Parameter:
   --    +Part: the part
   --  @Return: the anchor
   function Anchor (Part : in Part_Type) return String;

   --  ----------------------------------------------------------------------
   --  @Function: Has_Anchor
   --  @Description: Returns wether the part has an anchor for hyperlinking
   --    or not.
   --  @Parameter:
   --    +Part: the part
   --  @Return: true if part can be linked, false otherwise
   function Has_Anchor (Part : in Part_Type) return Boolean;

   --  ----------------------------------------------------------------------
   --  @Function: Set_Anchor
   --  @Description: Sets the part's anchor for hyperlinking.
   --  @Parameter:
   --    +Part: the part
   --    +Anchor: the anchor
   procedure Set_Anchor (Part : in out Part_Type; Anchor : in String);

   --  ----------------------------------------------------------------------
   --  @Function: Title
   --  @Description: Returns the part's title.
   --  @Parameter:
   --    +Part: the part
   --  @Return: the title
   function Title (Part : in Part_Type) return String;

   --  ----------------------------------------------------------------------
   --  @Function: Has_Title
   --  @Description: Returns wether the part has a title or not.
   --  @Parameter:
   --    +Part: the part
   --  @Return: true if part is titled, false otherwise
   function Has_Title (Part : in Part_Type) return Boolean;

   --  ----------------------------------------------------------------------
   --  @Function: Level
   --  @Description: Returns the part's title level.
   --  @Parameter:
   --    +Part: the part
   --  @Return: the title level
   function Level (Part : in Part_Type) return Level_Type;

   --  ----------------------------------------------------------------------
   --  @Function: Set_Title
   --  @Description: Sets the part's title and title level.
   --  @Parameter:
   --    +Part: the part
   --    +Title: the title
   --    +Level: the title level
   procedure Set_Title
     (Part  : in out Part_Type;
      Title : in     String;
      Level : in     Level_Type);

private

   package Attr_Vectors is new Ada.Containers.Vectors
     (Index_Type   => Natural,
      Element_Type => ASU.Unbounded_String,
      "="          => ASU."=");

   type Part_Record_Type;

   type Part_Type is access Part_Record_Type;

   package Part_Vectors is new Ada.Containers.Vectors
     (Index_Type   => Natural,
      Element_Type => Part_Type,
      "="          => "=");

   type Part_Record_Type is record
      Attr_Before : Attr_Vectors.Vector  := Attr_Vectors.Empty_Vector;
      Attr_After  : Attr_Vectors.Vector  := Attr_Vectors.Empty_Vector;
      Parts       : Part_Vectors.Vector  := Part_Vectors.Empty_Vector;
      Value       : ASU.Unbounded_String := ASU.Null_Unbounded_String;
      Anchor      : ASU.Unbounded_String := ASU.Null_Unbounded_String;
      Title       : ASU.Unbounded_String := ASU.Null_Unbounded_String;
      Level       : Level_Type           := 0;
   end record;

   --  ----------------------------------------------------------------------
   --  @Function: Vec_To_Arr
   --  @Description: Converts a vector to an array
   function Vec_To_Arr (Vec : Attr_Vectors.Vector) return Attributes_Type;

   --  ----------------------------------------------------------------------
   --  @Function: Vec_To_Arr
   --  @Description: Converts a vector to an array
   function Vec_To_Arr (Vec : Part_Vectors.Vector) return Parts_Type;

end Part;
